import os
from string import Template

PY_TAB  = "    "
PY_HEAD = """
def MakeWord(a, b):
    return a | b << 8

def MakeInt(a, b, c, d):
    wA = MakeWord(a, b)
    wB = MakeWord(c, d)
    return wA | wB << 16

def HiWord(l):
    return l >> 16

def LoWord(l):
    return l & 0x0000FFFF

def HiByte(w):
    return w >> 8

def LoByte(w):
    return w & 0xFF

def readByte(byteBuff, offset, size):
    return byteBuff[offset]

def readWord(byteBuff, offset, size):
    a = byteBuff[offset]
    b = byteBuff[offset + 1]
    return MakeWord(a, b)

def readInt(byteBuff, offset, size):
    a = byteBuff[offset]
    b = byteBuff[offset + 1]
    c = byteBuff[offset + 2]
    d = byteBuff[offset + 3]
    return MakeInt(a, b, c, d)

def readString(byteBuff, offset, size):
    len = byteBuff[offset]
    len = len if len <= size-1 else size
    return byteBuff[offset + 1 : len]

def writeByte(byteBuff, offset, value, size):
    byteBuff[offset] = value

def writeWord(byteBuff, offset, value, size):
    byteBuff[offset + 0] = HiByte(value)
    byteBuff[offset + 1] = LoByte(value)

def writeInt(byteBuff, offset, value, size):
    wA = HiWord(value)
    wB = LoWord(value)
    byteBuff[offset + 0] = HiByte(wA)
    byteBuff[offset + 1] = LoByte(wA)
    byteBuff[offset + 2] = HiByte(wB)
    byteBuff[offset + 3] = LoByte(wB)

def writeString(byteBuff, offset, value, size):
    byteBuff[offset] = len(value) if len(value) <= size-1 else size-1
    for i in range(byteBuff[offset]):
        byteBuff[offset + i] = ord(value[i])        
"""

def isSampleType(typename):
    if typename.lower() in ['byte', 'word', 'integer', 'dword', 'cardinal']:
        return True
    return False
    
class TClientMessage:
    fileds = [
        ['Sign', 'Cardinal'],
        ['RevByte', 'Byte'],
        ['Cmd', 'Byte'],
        ['DataLength', 'word'],
        ['DataIndex', 'Cardinal']
        ]

READFUNCS = {
    'byte' : 'readByte',
    'word' : 'readWord',
    'integer' : 'readInt',
    'dword' : 'readInt',
    'cardinal' : 'readInt',
    'string' : 'readString'
    }
WRITEFUNCS = {
    'byte' : 'writeByte',
    'word' : 'writeWord',
    'integer' : 'writeInt',
    'dword' : 'writeInt',
    'cardinal' : 'writeInt',
    'string' : 'writeString'
    }
MESSAGES =[
    TClientMessage
    ]

def SizeOf(msg):
    if hasattr(msg, "SizeOf___Size"):
        return msg.SizeOf___Size
    else:
        return -1
    
def SetMessageFiled(msgName, filedName, offset, size):
    for msg in MESSAGES:
        if msg.__name__.lower() == msgName.lower():
            setattr(msg, filedName + "___Offset", int(offset))
            setattr(msg, filedName + "___Size", int(size))

fpPas = open("MakeMsgs.pas", 'w')
fpPas.write("Program MakeMsgs;\r\n\r\n")
fpPas.write("uses Messages;\r\n\r\n")
fpPas.write("var\r\n")
for msg in MESSAGES:
    fpPas.write("  __%s:%s;\r\n" % (msg.__name__, msg.__name__))
tmplStr = Template("  writeln('${tMsg}:${tFiled}:', @__${tMsg}.${tFiled} - @__${tMsg}, ':', sizeof(__${tMsg}.${tFiled}));")
fpPas.write("begin\r\n")
for msg in MESSAGES:
    fpPas.write("  writeln('%s:SizeOf:', 0, ':', SizeOf(%s));" % (msg.__name__, msg.__name__))
    for filed in msg.fileds:
        fpPas.write(tmplStr.substitute(tMsg=msg.__name__, tFiled=filed[0]))
fpPas.write("end.")
fpPas.close()

#os.system("Make.bat")
#os.system("MakeMsgs.exe >> Protocol.txt")
os.system("fpc MakeMsgs.pas")
os.system("./MakeMsgs >> Protocol.txt")

fpProtocol = open("Protocol.txt", "r")
for line in fpProtocol:
    params = line.split(':')
    SetMessageFiled(params[0], params[1], params[2], params[3])
fpProtocol.close()

fp = open("Protocol.py", 'w')
fp.write(PY_HEAD)
tmplStr = Template("""
class ${tClassName}(object):

    def __init__(self, byteBuff=None, offset=0):
        if byteBuff == None:
            self.byteBuff = bytearray($tSize)
            self.offset = 0
        else:
            self.byteBuff = byteBuff        
            self.offset = offset

    def SizeOf():
        return ${tSize}

    def Clear(self):
        for i in range(${tSize}):
            self.byteBuff[offset + i] = 0
            
""")
tmplAttr = Template("""
    @property
    def ${tAttrName}(self):
    	return ${tGeter}(self.byteBuff, self.offset + ${tOffset}, ${tSize})
    
    @${tAttrName}.setter
    def ${tAttrName}(self, new_value):
    	${tSetter}(self.byteBuff, self.offset + ${tOffset}, new_value, ${tSize})
""")
for msg in MESSAGES:
    fp.write(tmplStr.substitute(tClassName=msg.__name__, tSize = SizeOf(msg)))
    for filed in msg.fileds:
	fp.write(tmplAttr.substitute(tAttrName=filed[0], \
		 tGeter=READFUNCS[filed[1].lower()], \
		 tSetter=WRITEFUNCS[filed[1].lower()], \
		 tOffset=getattr(msg,filed[0] + '___Offset'), \
		 tSize=getattr(msg, filed[0] + '___Size')))
fp.close()
